/*
 * $Id: GeodataUtilities.java 42 2013-04-17 15:33:59Z gabakyan $
 * $Author: gabakyan $
 * $Revision: 42 $
 * $Date: 2013-04-17 15:33:59 +0000 (Wed, 17 Apr 2013) $
 *
 * Copyright (c) 2013 Supply Chain Intelligence (SCI), Inc.
 * http://www.scintelligence.com/, Email: info@scintelligence.com
 * All rights reserved.
 *
 * This file is part of Logistics Map.
 *
 * Logistics Map is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * Logistics Map is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Logistics Map.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.sci.logisticsmap.service.support;

import com.sci.logisticsmap.data.model.GeodataModel;
import com.sci.logisticsmap.data.model.LocationModel;
import com.sci.logisticsmap.data.model.location.DCModel;
import com.sci.logisticsmap.support.Constants;
import com.sci.logisticsmap.support.Utilities;
import com.sci.logisticsmap.support.model.GeodataStatistics;
import com.sci.logisticsmap.support.model.geocoding.LatLng;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * The utility class which provides helper methods for manipulating the Geodata.
 *
 * @author gabakyan@gmail.com (Last modified by $Author: gabakyan $)
 * @version $Revision: 42 $
 */
public class GeodataUtilities {
    /**
     * The Geodata filename prefix.
     */
    public static final String GEODATA_FILENAME_PREFIX = "Geodata";
    /**
     * The Geodata file default extension.
     */
    public static final String GEODATA_FILE_DEFAULT_EXTENSION = ".csv";

    /**
     * The private constructor.
     */
    private GeodataUtilities() {
    }

    /**
     * Fixes the LatLng precision.
     *
     * @param latLng the LatLng model.
     */
    public static void fixLatLngPrecision(LatLng latLng) {
        fixLatLngPrecision(latLng, Constants.LAT_LNG_DEFAULT_PRECISION);
    }

    /**
     * Fixes the LatLng precision.
     *
     * @param latLng the LatLng model.
     * @param precision the precision.
     */
    public static void fixLatLngPrecision(LatLng latLng, int precision) {
        latLng.setLat(latLng.getLat().setScale(precision, BigDecimal.ROUND_HALF_EVEN));
        latLng.setLng(latLng.getLng().setScale(precision, BigDecimal.ROUND_HALF_EVEN));
    }

    /**
     * Updates locations position based on their order.
     *
     * @param locations location models list.
     */
    public static void updateLocationsPosition(List<LocationModel> locations) {
        int position = 1;
        int dcPosition = 0;

        int i = 0;
        int dcIndex = -1;
        for (LocationModel location : locations) {
            if (location instanceof DCModel) {
                location.setPosition(dcPosition);
                dcIndex = i;
            } else {
                location.setPosition(position++);
            }
            i++;
        }

        if (dcIndex > 0) {
            locations.add(0, locations.remove(dcIndex));
        }
    }

//    /**
//     * Retrieves the geocoded Locations count.
//     *
//     * @param geodata The Geodata.
//     *
//     * @return The geocoded Locations count.
//     */
//    public static int getGeocodedLocationCount(GeodataModel geodata) {
//        return getLocationCountByStatus(geodata, LocationStatus.G);
//    }
//    /**
//     * Retrieves the not geocoded Locations count.
//     *
//     * @param geodata The Geodata.
//     *
//     * @return The not geocoded Locations count.
//     */
//    public static int getNotGeocodedLocationCount(GeodataModel geodata) {
//        return getLocationCountByStatus(geodata, LocationStatus.NG);
//    }
//    /**
//     * Retrieves the geocoding failed Locations count.
//     *
//     * @param geodata The Geodata.
//     *
//     * @return The geocoding failed Locations count.
//     */
//    public static int getGeocodingFailedLocationCount(GeodataModel geodata) {
//        return getLocationCountByStatus(geodata, LocationStatus.GF);
//    }
//
//    /**
//     * Retrieves the Locations count by the status.
//     *
//     * @param geodata The Geodata.
//     * @param locationStatus The Location status.
//     *
//     * @return The Locations count by the status.
//     */
//    private static int getLocationCountByStatus(GeodataModel geodata, String locationStatus) {
//        int count = 0;
//        for (Location location : geodata.getLocations()) {
//            if (location.getStatus() != null && location.getStatus().equals(locationStatus)) {
//                count++;
//            }
//        }
//        return count;
//    }

    /**
     * Builds the Geodata light statistics.
     *
     * @param statistics The Geodata statistics.
     *
     * @return The built Geodata light statistics.
     */
    public static int[] buildGeodataLightStatistics(GeodataStatistics statistics) {
        return new int[] {
                statistics.getGeocodedLocationCount(),
                statistics.getNotGeocodedLocationCount(),
                statistics.getGeocodingFailedLocationCount()
        };
    }

    /**
     * Builds the Location full address.
     *
     * @param location The Location.
     *
     * @return The built Location full address.
     */
    public static String buildLocationFullAddress(LocationModel location) {
        StringBuilder fullAddressBuilder = new StringBuilder();

        fullAddressBuilder.append(location.getAddress());
        if (location.getCity() != null) {
            fullAddressBuilder.append(", ").append(location.getCity());
        }
        if (location.getState() != null) {
            fullAddressBuilder.append(", ").append(location.getState());
        }
        if (location.getZipCode() != null) {
            fullAddressBuilder.append(", ").append(location.getZipCode());
        }
        if (location.getCountry() != null) {
            fullAddressBuilder.append(", ").append(location.getCountry());
        }

        return fullAddressBuilder.toString();
    }

    /**
     * Builds the Geodata file name.
     *
     * @param geodata the Geodata model.
     *
     * @return the built Geodata file name.
     */
    public static String buildGeodataFilename(GeodataModel geodata) {
        return buildGeodataFilename(geodata, GEODATA_FILE_DEFAULT_EXTENSION);
    }

    /**
     * Builds the Geodata file name.
     *
     * @param geodata the Geodata model.
     * @param fileExtension the Geodata file extension.
     *
     * @return the built Geodata file name.
     */
    public static String buildGeodataFilename(GeodataModel geodata, String fileExtension) {
        StringBuilder filename = new StringBuilder();

        // adding the file name prefix
        filename.append(GEODATA_FILENAME_PREFIX);

        // adding the file name date marker
        Date date = geodata.getCreationDate();
        if (date == null) {
            date = new Date();
        }
        filename.append(Utilities.formatFilenameDateMarker(date));

        // adding the file extension
        if (fileExtension != null) {
            filename.append(fileExtension);
        }

        return filename.toString();
    }
}
